package com.example.opengldemo.earth;

import android.opengl.GLES30;
import android.view.View;

import com.example.opengldemo._07_book_demo.MySurfaceView;
import com.example.opengldemo.util.MatrixState;
import com.example.opengldemo.util.ShaderHandle;
import com.example.opengldemo.util.ShaderUtil;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.ArrayList;

public class CloudDemo {


    String mVertexShader;
    String mFragmentShader;

    FloatBuffer mVertexBuffer;
    FloatBuffer   mTexCoorBuffer;
    int vCount=0;

    public CloudDemo(View view, float r)
    {
        initVertexData(r);
        initShader(view);
    }

    public void initVertexData(float r)
    {

        final float UNIT_SIZE=0.5f;
        ArrayList<Float> alVertix=new ArrayList<Float>();
        final float angleSpan=10f;
        for(float vAngle=90;vAngle>-90;vAngle=vAngle-angleSpan)
        {
            for(float hAngle=360;hAngle>0;hAngle=hAngle-angleSpan)
            {
                double xozLength=r*UNIT_SIZE*Math.cos(Math.toRadians(vAngle));
                float x1=(float)(xozLength*Math.cos(Math.toRadians(hAngle)));
                float z1=(float)(xozLength*Math.sin(Math.toRadians(hAngle)));
                float y1=(float)(r*UNIT_SIZE*Math.sin(Math.toRadians(vAngle)));

                xozLength=r*UNIT_SIZE*Math.cos(Math.toRadians(vAngle-angleSpan));
                float x2=(float)(xozLength*Math.cos(Math.toRadians(hAngle)));
                float z2=(float)(xozLength*Math.sin(Math.toRadians(hAngle)));
                float y2=(float)(r*UNIT_SIZE*Math.sin(Math.toRadians(vAngle-angleSpan)));

                xozLength=r*UNIT_SIZE*Math.cos(Math.toRadians(vAngle-angleSpan));
                float x3=(float)(xozLength*Math.cos(Math.toRadians(hAngle-angleSpan)));
                float z3=(float)(xozLength*Math.sin(Math.toRadians(hAngle-angleSpan)));
                float y3=(float)(r*UNIT_SIZE*Math.sin(Math.toRadians(vAngle-angleSpan)));

                xozLength=r*UNIT_SIZE*Math.cos(Math.toRadians(vAngle));
                float x4=(float)(xozLength*Math.cos(Math.toRadians(hAngle-angleSpan)));
                float z4=(float)(xozLength*Math.sin(Math.toRadians(hAngle-angleSpan)));
                float y4=(float)(r*UNIT_SIZE*Math.sin(Math.toRadians(vAngle)));

                //������һ������
                alVertix.add(x1);alVertix.add(y1);alVertix.add(z1);
                alVertix.add(x2);alVertix.add(y2);alVertix.add(z2);
                alVertix.add(x4);alVertix.add(y4);alVertix.add(z4);
                //�����ڶ�������
                alVertix.add(x4);alVertix.add(y4);alVertix.add(z4);
                alVertix.add(x2);alVertix.add(y2);alVertix.add(z2);
                alVertix.add(x3);alVertix.add(y3);alVertix.add(z3);
            }
        }
        vCount=alVertix.size()/3;
        float vertices[]=new float[vCount*3];
        for(int i=0;i<alVertix.size();i++)
        {
            vertices[i]=alVertix.get(i);
        }

        ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
        vbb.order(ByteOrder.nativeOrder());
        mVertexBuffer = vbb.asFloatBuffer();
        mVertexBuffer.put(vertices);
        mVertexBuffer.position(0);
        float[] texCoor=generateTexCoor
                (
                        (int)(360/angleSpan),
                        (int)(180/angleSpan)
                );
        ByteBuffer llbb = ByteBuffer.allocateDirect(texCoor.length*4);
        llbb.order(ByteOrder.nativeOrder());
        mTexCoorBuffer=llbb.asFloatBuffer();
        mTexCoorBuffer.put(texCoor);
        mTexCoorBuffer.position(0);

    }

    ShaderHandle shaderHandle ;
    public void initShader(View mv)
    {
        mVertexShader= ShaderUtil.loadFromAssetsFile("earth/vertex_cloud.sh", mv.getResources());
        mFragmentShader=ShaderUtil.loadFromAssetsFile("earth/fragment_cloud.sh", mv.getResources());
        shaderHandle = new ShaderHandle(ShaderUtil.createProgram(mVertexShader, mFragmentShader));

    }

    public void drawSelf(int texId)
    {

        GLES30.glUseProgram(shaderHandle.getProgram());

        GLES30.glUniformMatrix4fv(shaderHandle.get_U_MVPMatrixHandle(), 1, false, MatrixState.getFinalMatrix(), 0);

        GLES30.glUniformMatrix4fv(shaderHandle.get_U_MMatrixhandle(), 1, false, MatrixState.getMMatrix(), 0);

        GLES30.glUniform3fv(shaderHandle.get_U_CameraHandle(), 1, MatrixState.cameraLocationFB);

        GLES30.glUniform3fv(shaderHandle.get_U_LightLHandle(), 1, MatrixState.lightLocationFB);


        GLES30.glVertexAttribPointer
                (
                        shaderHandle.get_A_PositionHandle(),
                        3,
                        GLES30.GL_FLOAT,
                        false,
                        3*4,
                        mVertexBuffer
                );

        GLES30.glVertexAttribPointer
                (
                        shaderHandle.get_A_TexCoorsHandle(),
                        2,
                        GLES30.GL_FLOAT,
                        false,
                        2*4,
                        mTexCoorBuffer
                );
        GLES30.glVertexAttribPointer
                (
                        shaderHandle.get_A_NormalHandle(),
                        3,
                        GLES30.GL_FLOAT,
                        false,
                        3*4,
                        mVertexBuffer
                );

        GLES30.glEnableVertexAttribArray(shaderHandle.get_A_PositionHandle());

        GLES30.glEnableVertexAttribArray(shaderHandle.get_A_TexCoorsHandle());

        GLES30.glEnableVertexAttribArray(shaderHandle.get_A_NormalHandle());

        GLES30.glActiveTexture(GLES30.GL_TEXTURE0);
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, texId);

        GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, vCount);
    }


    public float[] generateTexCoor(int bw,int bh)
    {
        float[] result=new float[bw*bh*6*2];
        float sizew=1.0f/bw;
        float sizeh=1.0f/bh;
        int c=0;
        for(int i=0;i<bh;i++)
        {
            for(int j=0;j<bw;j++)
            {

                float s=j*sizew;
                float t=i*sizeh;

                result[c++]=s;
                result[c++]=t;

                result[c++]=s;
                result[c++]=t+sizeh;

                result[c++]=s+sizew;
                result[c++]=t;

                result[c++]=s+sizew;
                result[c++]=t;

                result[c++]=s;
                result[c++]=t+sizeh;

                result[c++]=s+sizew;
                result[c++]=t+sizeh;
            }
        }
        return result;
    }
}